#include "symtable.h"
#pragma once
union data_type
{
    char *type_id;
    int type_type;
    int type_int;
    float type_float;
    Type sym_type;
    Array sym_array;
    Structure sym_structure;
    Para sym_para;
    Func sym_func;
    Symbol sym_symbol;
};

typedef struct Node
{
    int type; //节点语法成分
    union data_type data;
    int lineno;
    int num;               //儿子个数
    struct Node *child[7]; //儿子节点,单个节点的儿子最多7个
} NODE;

enum SYM_TYPE
{
    S_TYPE,
    S_ARRAY,
    S_STRUCTURE,
    S_PARA,
    S_FUNC,
    S_SYMBOL,
    _INT,
    _FLOAT,
    _TYPE,
    _ID,
    _SEMI,
    _COMMA,
    _ASSIGNOP,
    _RELOP,
    _PLUS,
    _MINUS,
    _STAR,
    _DIV,
    _AND,
    _OR,
    _DOT,
    _NOT,
    _LP,
    _RP,
    _LB,
    _RB,
    _LC,
    _RC,
    _STRUCT,
    _RETURN,
    _IF,
    _ELSE,
    _WHILE,
    _Program,
    _ExtDeflist,
    _ExtDef,
    _Specifier,
    _ExtDeclist,
    _FunDec,
    _CompSt,
    _VarDec,
    _StructSpecifier,
    _OptTag,
    _DefList,
    _Tag,
    _VarList,
    _ParamDec,
    _StmtList,
    _Stmt,
    _Exp,
    _Def,
    _DecList,
    _Dec,
    _Args,
    _Error
};

NODE *createNode(int type, int num, int lineno, union data_type *data);
void output(NODE *node, int level);

//语法分析树的分析过程

/*
Program : ExtDeflist
*/
void Program(NODE *node);

/*
ExtDeflist  : ExtDef ExtDeflist | empty
*/
void ExtDeflist(NODE *node);

/*
ExtDef  : Specifier ExtDeclist SEMI | Specifier SEMI | Specifier FunDec CompSt
*/
void ExtDef(NODE *node);

/*
ExtDeclist  : VarDec | VarDec COMMA ExtDeclist
*/
void ExtDeclist(NODE *node, Type type);

/*
Specifier   : TYPE | StructSpecifier
*/
NODE *Specifier(NODE *node);

/*
StructSpecifier : STRUCT OptTag LC DefList RC | STRUCT Tag
*/
NODE *StructSpecifier(NODE *node, char **name, int *num);

/*
OptTag : ID | empty
*/
char *OptTag(NODE *node);

/*
Tag : ID
*/
char *Tag(NODE *node);

/*
VarDec : ID | VarDec LB INT RB
*/
Type VarDec(NODE *node, Type type, FieldList head, int kind);

/*
FunDec : ID LP VarList RP | ID LP RP
*/
NODE *FunDec(NODE *node, Type ret, char **name);

/*
VarList : ParamDec COMMA VarList | ParamDec
*/
void VarList(NODE *node, Para head, int *num);

/*
ParamDec : Specifier VarDec
*/
Type ParamDec(NODE *node);

/*
CompSt : LC DefList StmtList RC
*/
void Compst(NODE *node);
/*
StmtList : Stmt StmtList | empty
*/
void StmtList(NODE *node);

/*
Stmt :  Exp SEMI
    | CompSt
    | RETURN Exp SEMI
    | IF LP Exp RP Stmt %prec LOWER_THAN_ELSE
    | IF LP Exp RP Stmt ELSE Stmt
    | WHILE LP Exp RP Stmt
*/
void Stmt(NODE *node);
/*
DefList : Def DefList | empty
*/
void DefList(NODE *node, FieldList head, int kind);

/*
Def : Specifier DecList SEMI
*/
void Def(NODE *node, FieldList head, int kind);

/*
DecList : Dec | Dec COMMA DecList
*/
void Declist(NODE *node, Type type, FieldList head, int kind);

/*
Dec : VarDec | VarDec ASSIGNOP Exp
*/
void Dec(NODE *node, Type type, FieldList head, int kind);

/*
Exp : Exp ASSIGNOP Exp
    | Exp AND Exp
    | Exp OR Exp
    | Exp RELOP Exp
    | Exp PLUS Exp
    | Exp MINUS Exp
    | Exp STAR Exp
    | Exp DIV Exp
    | LP Exp RP
    | MINUS Exp %prec NEG
    | NOT Exp
    | ID LP Args RP
    | ID LP RP
    | Exp LB Exp RB
    | Exp DOT ID
    | ID
    | INT
    | FLOAT
返回EXP计算结果的类型
*/
NODE *Exp(NODE *node);
NODE *ExpOneNode(NODE *node);
NODE *ExpTwoNode(NODE *node);
NODE *ExpThreeNode(NODE *node);
NODE *ExpFourNode(NODE *node);
/*
Args : Exp COMMA Args  | Exp
*/
NODE *Args(NODE *node, Para para, int paranum);

char *TID(NODE *node);
float TFLOAT(NODE *node);
int TINT(NODE *node);
NODE *TTYPE(NODE *node);

//打印错误信息并返回NULL
NODE *myError(const char *msg, int line, const char *name);
